package com.kp.fintech.admin.controller;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.common.collect.Maps;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import com.google.code.kaptcha.Constants;
import com.google.code.kaptcha.Producer;
import com.kp.fintech.admin.model.SysUser;
import com.kp.fintech.admin.service.SysLoginLogService;
import com.kp.fintech.admin.service.SysUserService;
import com.kp.fintech.admin.util.IPUtils;
import com.kp.fintech.admin.util.PasswordUtils;
import com.kp.fintech.admin.vo.LoginBean;
import com.kp.fintech.common.utils.IOUtils;
import com.kp.fintech.core.http.HttpResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

/**
 * 登录控制器
 *
 * @author chenming
 * @date Jan 14, 2019
 */
@RestController
@RequestMapping("/sys")
public class SysLoginController {

    @Resource(name = "captchaProducer")
    private Producer captchaProducer;

    @Resource(name = "captchaProducerMath")
    private Producer captchaProducerMath;

    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysLoginLogService sysLoginLogService;

    @Autowired
    private LoadBalancerClient loadBalancer;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RestTemplate restTemplate;

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @ApiOperation(value = "获取二维码", notes = "登录验证二维码")
    @GetMapping("/captcha.jpg")
    public void captcha(@RequestParam(value = "type") String type, @RequestParam(value = "date_time") String date_time, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, ParseException {

        ServletOutputStream out = null;

        response.setDateHeader("Expires", 0);
        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
        response.addHeader("Cache-Control", "post-check=0, pre-check=0");
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-store, no-cache");
        response.setContentType("image/jpeg");

        String capStr = null;
        String text = null;
        BufferedImage image = null;
        logger.debug("*****验证码类型是*****" + type);

        Date date = new Date(Long.parseLong(date_time));
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String sTime = formatter.format(date);
        logger.debug("*****时间是*****" + sTime);

        if ("math".equals(type)) {
            String capText = captchaProducerMath.createText();
            capStr = capText.substring(0, capText.lastIndexOf("@"));
            text = capText.substring(capText.lastIndexOf("@") + 1);
            image = captchaProducerMath.createImage(capStr);
        } else if ("char".equals(type)) {
            text = captchaProducer.createText();
            image = captchaProducer.createImage(text);
        } else {
            return;
        }

        //通过ValueOperations设置值到redis中
        ValueOperations ops = redisTemplate.opsForValue();
        ops.set(Constants.KAPTCHA_SESSION_KEY, text, 60, TimeUnit.SECONDS);
        //logger.debug("*****session的有效时间是(秒)*****" + interval+"****session的id*****"+sessionId);

        out = response.getOutputStream();
        ImageIO.write(image, "jpg", out);
        IOUtils.closeQuietly(out);
    }


    /**
     * 登录接口
     */
    @ApiOperation(value = "登录验证接口", notes = "登录验证接口")
    @ApiImplicitParam(name ="loginBean",value="用户对象",required=true,dataType = "LoginBean")
    @PostMapping(value = "/login")
    public HttpResult login(@RequestBody LoginBean loginBean, HttpServletRequest request) throws IOException {
        String username = loginBean.getAccount();
        String password = loginBean.getPassword();
        String captchaStr = loginBean.getCaptcha();

        request.setAttribute("userName", username); //request 设置 userName ,便于AOP时获取
        //logger.info("*******当前线程ID是{}*******",Thread.currentThread().getId());
        //通过ValueOperations从redis中获取值
        try {
            ValueOperations ops = redisTemplate.opsForValue();
            String captcha = (String) ops.get(Constants.KAPTCHA_SESSION_KEY); //获取
        } catch (Exception e) {
            return HttpResult.error(20000, "调用缓存服务器获取验证码数据异常");
        }

        /*if (captcha == null) {
            return HttpResult.error("验证码已失效");
        }
        if (!captcha.equals(captchaStr)) {
            return HttpResult.error("验证码不正确");
        }*/
        // 用户信息
        SysUser user = sysUserService.findByName(username);
        // 账号不存在、密码错误
        if (user == null) {
            return HttpResult.error("账号不存在");
        }
        if (!PasswordUtils.matches(user.getSalt(), password, user.getPassword())) {
            return HttpResult.error("密码不正确");
        }
        // 账号锁定
        if (user.getStatus() == 0) {
            return HttpResult.error("账号已被锁定,请联系管理员");
        }


        // 生成远程调用的传递参数对象
        HttpHeaders headers = new HttpHeaders(); // http请求头
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8); // 请求头设置属性
        Map<String, Object> uriParam = Maps.newHashMap();

        uriParam.put("remoteAddress", request.getRemoteAddr());
        uriParam.put("sessionId", request.getSession().getId());
        uriParam.put("loginBean", loginBean);
        HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<Map<String, Object>>(uriParam, headers);

        ServiceInstance serviceInstance = loadBalancer.choose("fintech-oauth");
        logger.debug("服务名称：{}", serviceInstance.getServiceId());
        String uriStr = "http://" + serviceInstance.getServiceId() + "/oauth/oauth-token";
        logger.info("调用微服务fintech-oauth的uri为：{}", uriStr);


        // 记录登录日志
        String ipAddress = IPUtils.getIpAddr(request);
        logger.info("登录的用户名：{} 登录IP地址是 {} ", username, ipAddress);
        sysLoginLogService.writeLoginLog(username, ipAddress);
        //调用认证微服务，获取令牌号

        try {
            String tokenNo = null;  // 生成令牌token
            tokenNo = restTemplate.postForObject(uriStr, requestEntity, String.class);
            if (tokenNo == null) {
                return HttpResult.error(20001, "缓存服务异常,获取tokenNo为空");
            } else {
                Map tokenMap = new HashMap();
                tokenMap.put("token", tokenNo);
                return HttpResult.ok(tokenMap);
            }
        } catch (RestClientException e) {
            return HttpResult.error(20001, "缓存服务异常,获取tokenNo失败");
        }

    }


}
